package com.xhga.transaction.log.impl;

import com.xhga.transaction.common.entity.TransactionLog;
import com.xhga.transaction.common.service.TransactionLogService;
import com.xhga.transaction.common.util.UniqueUtil;
import com.xhga.transaction.log.dao.TransactionLogMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * Created by HuaWeiBo on 2019/4/6.
 */
@Service("transactionLogService")
public class TransactionLogServiceImpl implements TransactionLogService {

    private static final Logger logger = LoggerFactory.getLogger(TransactionLogServiceImpl.class);

    @Autowired
    private TransactionLogMapper transactionLogMapper;

    @Override
    public String getCentreNo(String type, String[] names, int count, String name) {
        return UniqueUtil.getCentreNo(type, names, count, name);
    }

    @Override
    public void updateCentreNo(String type, String name, int count) {
        UniqueUtil.updateCentreNo(type, name);
    }

    @Override
    public synchronized int addTransactionLog(TransactionLog transactionLog) {
        String centreNo = transactionLog.getCentreNo();
        TransactionLog log = transactionLogMapper.getTransactionLogByCentreNo(centreNo);
        if (log != null) {
            logger.info("XHGA事务--已存在日志记录.no:{}", centreNo);
            return 0;
        }
        return transactionLogMapper.insertSelective(transactionLog);
    }

    @Override
    public void updateFailedCount(String centreNo, String serverName) {
        logger.info("XHGA事务操作失败--serverName:{}.", serverName);
        // 修改分布式状态
        TransactionLog centre = transactionLogMapper.getTransactionLogByCentreNo(centreNo);
        if (centre == null) {
            return;
        }
        centre.setPrepareCount(0);
        centre.setFailedCount(1);
        transactionLogMapper.updateByPrimaryKeySelective(centre);
    }

    @Override
    public void updatePrepareCount(String centreNo, String serverName) {
        int i = transactionLogMapper.updatePrepareCount(centreNo);
        String result = i > 0 ? "ok" : "fail";
        logger.info("XHGA事务--修改准备状态:{},结果:{}.", serverName, result);
    }

    @Override
    public int returnFailedCount(String centreNo){
        logger.info("XHGA事务--查询失败个数:centreNo{}", centreNo);
        while (true) {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            TransactionLog transaction = transactionLogMapper.getTransactionLogByCentreNo(centreNo);
            Integer prepareCount = transaction.getPrepareCount();
            Integer failedCount = transaction.getFailedCount();
            // 回滚
            if (failedCount > 0) {
                return 1;
            }
            if (prepareCount <= 0){
                if (failedCount != 0) {
                    return 1;
                }else {
                    return 0;
                }
            }
        }
    }

    /**
     * 预完成成功,查询失败次数
     * 操作简介：
     * 1.失败次数>0返回.
     * 2.预操作都以完成：失败次数>0返回 / 返回成功.
     * @param centreNo
     * @return
     * @throws RuntimeException
     */
    @Override
    public int returnFailedCountException(String centreNo) throws RuntimeException {
        logger.info("查询失败个数--抛异常:centreNo{}.", centreNo);
        while (true) {
            TransactionLog transaction = transactionLogMapper.getTransactionLogByCentreNo(centreNo);
            System.out.println(transaction);
            Integer prepareCount = transaction.getPrepareCount();
            Integer failedCount = transaction.getFailedCount();
            // 回滚
            if (failedCount > 0) {
                throw new RuntimeException();
            }
            if (prepareCount <= 0){
                if (failedCount != 0) {
                    throw new RuntimeException();
                }else {
                    return 0;
                }
            }
        }
    }

    @Override
    public int returnFailedCountNoDelay(String centreNo) {
        logger.info("NoDelay查询失败个数:centreNo{}.", centreNo);
        TransactionLog transaction;
        while (true) {
            transaction = transactionLogMapper.getTransactionLogByCentreNo(centreNo);
            Integer prepareCount = transaction.getPrepareCount();
            Integer failedCount = transaction.getFailedCount();
            // 回滚
            if (failedCount > 0) {
                return 1;
            }
            if (prepareCount <= 0){
                if (failedCount != 0) {
                    return 1;
                }else {
                    return 0;
                }
            }
        }
    }

    @Override
    public int returnFailedCountExceptionNoDelay(String centreNo) throws RuntimeException {
        TransactionLog transaction;
        while (true) {
            transaction = transactionLogMapper.getTransactionLogByCentreNo(centreNo);
            Integer prepareCount = transaction.getPrepareCount();
            Integer failedCount = transaction.getFailedCount();
            // 回滚
            if (failedCount > 0) {
                throw new RuntimeException();
            }
            if (prepareCount <= 0){
                if (failedCount != 0) {
                    throw new RuntimeException();
                }else {
                    return 0;
                }
            }
        }
    }
}
